home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / sound / bunked10.zip / PP.PAS < prev   
Pascal/Delphi Source File  |  1994-03-07  |  5KB  |  158 lines

  1. Program PlayPatch; {simple program to play .INS file on channel 0}
  2.  
  3. Type HSC_InstType = Record
  4.                      AmByte,                       {AM/VB/EG/KS/MFM}
  5.                      LkByte,                       {KSL/Volume}
  6.                      AdByte,                       {Attack/Decay}
  7.                      SrByte : Array[1..2] of Byte; {Sustain/Release}
  8.                      FbByte : Byte;                {Feedback/DuelOp}
  9.                      WfByte : Array[1..2] of Byte; {WaveForm Type}
  10.                      SlideByte : Byte;             {HSC internal byte (?)}
  11.                     End;
  12.  
  13.      RegConfigType = Record
  14.                       WaveEnab,                    {WaveForm Enable}
  15.                       Sp_Ks,                       {SpeechSyn/KeySplit}
  16.                       AmVb_Perc : Byte;            {Am/Vb depths/Percussion}
  17.                      End;
  18.  
  19.      ChnlRange = 0..8; {Available Channels}
  20.      OctRange  = 0..8; {Octive Range}
  21.  
  22. Const RegConfig : RegConfigType = (WaveEnab  : $20;  {WaveForm Enabled}
  23.                                    Sp_Ks     : $00;  {Speech Off/KeySplit Off}
  24.                                    AmVb_Perc : $00); {Am Dep: 1db
  25.                                                       Vb Dep: 7cent
  26.                                                       Percussion Mode Off}
  27.  
  28.       {list of freq range.. C# thru B and a higher C}
  29.  
  30.       NoteList : Array[1..12] of Word = ($016B, $0181, $0198, $01B0,
  31.                                          $01CA, $01E5, $0202, $0220,
  32.                                          $0241, $0263, $0287, $02AE);
  33.  
  34.       {mapping array for channel positions from register base}
  35.  
  36.       ChannelMap : Array[ChnlRange] of Byte = ($00, $01, $02, $08,
  37.                                                $09, $0A, $10, $11,
  38.                                                $12);
  39.  
  40. Var CurrentIns : HSC_InstType;
  41.  
  42. {write value to specific FM register in single OPL2/mono mode}
  43.  
  44. Procedure WriteFM(Reg, Value : Byte); Assembler;
  45. Asm
  46.  MOV DX, 0388h   {address port = 388h.. single OPL2/mono}
  47.  MOV AL, Reg
  48.  OUT DX, AL      {send register info to address port}
  49.  
  50.  MOV AH, 0       {set counter to 0}
  51. @Delay1:         {delay 3.3ms (6 port reads)}
  52.  IN  AL,  DX     {read address port}
  53.  INC AH          {increment counter}
  54.  CMP AH, 6       {there yet?}
  55.  JNE @Delay1     {no.. read port again}
  56.  
  57.  MOV DX, 0389h   {data port = 389h.. single OPL2/mono}
  58.  MOV AL, Value
  59.  OUT DX, AL      {send register value to data port}
  60.  
  61.  MOV AH, 0       {set counter to 0}
  62.  MOV DX, 0388h   {set address port for delay}
  63. @Delay2:         {delay 23ms (35 port reads)}
  64.  IN  AL,  DX     {read address port}
  65.  INC AH          {increment counter}
  66.  CMP AH, 35      {done yet?}
  67.  JNE @Delay2     {no.. read port again}
  68.  {ready for next port write}
  69. End;
  70.  
  71. {reset all FM registers to 0}
  72.  
  73. Procedure ResetFM;
  74.  
  75. Var Count : Byte;
  76.  
  77. Begin
  78.  For Count := $01 to $F5 do WriteFM(Count, $00);
  79. End;
  80.  
  81. {loads instrument file into HSC_InstType variable}
  82.  
  83. Function LoadInst(fName : String; Var Ins : HSC_InstType) : Boolean;
  84.  
  85. Var InsF : File of HSC_InstType;
  86.  
  87. Begin
  88.  Assign(InsF, fName);
  89.  {$I-} Reset(InsF); {$I+}
  90.  If IOResult <> 0 then LoadInst := False
  91.  Else Begin
  92.   {$I-} Read(InsF, Ins); {$I+}
  93.   If IOResult <> 0 then LoadInst := False
  94.   Else Begin
  95.    LoadInst := True;
  96.    Close(InsF);
  97.   End;
  98.  End;
  99. End;
  100.  
  101. {write instrument to specific channel}
  102.  
  103. Procedure WriteInst(Chnl : Byte; Ins : HSC_InstType);
  104.  
  105. Var OpCount,
  106.     OpMap    : Byte;
  107.  
  108. Begin
  109.  With RegConfig do
  110.  Begin
  111.   WriteFM($01, WaveEnab);  {enable WaveForm usage}
  112.   WriteFM($08, Sp_Ks);     {turn off Speech/Key Split}
  113.   WriteFM($BD, AmVb_Perc); {Am Depth = 1db / Vib Depth = 7cent / Percussion Mode Off}
  114.  End;
  115.  OpMap := 3;
  116.  With Ins do
  117.  Begin
  118.   For OpCount := 1 to 2 do {write first to the carrier.. then the modulator}
  119.   Begin
  120.   WriteFM($20+ChannelMap[Chnl]+OpMap, AmByte[OpCount]); {write AM/VB/EG/KS/MFM info}
  121.   WriteFM($40+ChannelMap[Chnl]+OpMap, LkByte[OpCount]); {write KS/Volume info}
  122.   WriteFM($60+ChannelMap[Chnl]+OpMap, AdByte[OpCount]); {write Attack/Decay info}
  123.   WriteFM($80+ChannelMap[Chnl]+OpMap, SrByte[OpCount]); {write Sustain/Release}
  124.   WriteFM($E0+ChannelMap[Chnl]+OpMap, WfByte[OpCount]); {write WaveForm info}
  125.   Dec(OpMap, 3);
  126.   End;
  127.   WriteFM($C0+Chnl, FbByte);   {write feedback/duel op info}
  128.  End;
  129. End;
  130.  
  131. {turn on voice on specific channel at specified octive/pitch}
  132.  
  133. Procedure Vox_On(Chnl : ChnlRange; Pitch : Word; Oct : OctRange);
  134. Begin
  135.  WriteFM($A0+Chnl, Lo(Pitch));
  136.  WriteFM($B0+Chnl, $20 or Hi(Pitch) or (Oct shl 2));
  137. End;
  138.  
  139. {turn off voice on specific channel}
  140.  
  141. Procedure Vox_Off(Chnl : Byte);
  142. Begin
  143.  WriteFM($B0+Chnl, $00);
  144. End;
  145.  
  146. Begin
  147.  WriteLn('usage: pp <patch.ins>');
  148.  WriteLn('run prog with no parameters to kill sound');
  149.  ResetFM; {reset FM registers}
  150.  If ParamCount <> 1 then Halt(0);
  151.  If Not LoadInst(ParamStr(1), CurrentIns) then {try and load instrument file}
  152.  Begin
  153.   WriteLn(ParamStr(1),' does not exist or is corrupt');
  154.   Halt(0);
  155.  End;
  156.  WriteInst(0, CurrentIns);   {write loaded instrument file to channel 0}
  157.  Vox_On(0, NoteList[12], 3); {turn on 0.. pitch C.. octive 3}
  158. End.